"""
查询用户购买的标准教辅中包含的与商品包版本属性相同的物料下视频专辑
"""
import threadpool
from business.subjectvideo.template.api_template import *
from base.request_new import RequestNew
from business.ssologin.login import user_login
from base.logcontrol import logger
import asyncio
from config import base_url
from bson import json_util
from copy import deepcopy
from datetime import datetime


class GetSubjectVideo:

    def __init__(self, user_id=None, mobile=None):
        self.result = dict()
        self.user_id = user_id
        self.mobile = mobile
        cookie = user_login()
        self.rt = RequestNew(cookie=cookie)
        self.main()

    def get_orders(self):
        """
        获取用户已付款的订单集合
        :return:{id}
        """
        req_get_orders = get_user_orders(user_id=self.user_id, phone=self.mobile)
        response, rep = self.rt.request_auto(**req_get_orders)
        logger.debug(f"\n\trep: {rep}\n")
        return [i for i, _ in rep.items()]

    def get_product_package(self, order_id):
        """
        获取订单包含的商品包id和版本
        :param order_id: 订单
        :return: 
        """
        response, rep = self.rt.request_auto(**get_order_info(order_id))
        return rep

    async def get_single_product(self, order_id, product_package_id):
        """
        获取商品包中的标准教辅(目前订单中没有单商品的类型,查询商品名中带有标准教辅的)
        :param order_id:
        :param product_package_id: 
        :return: 
        """
        response, rep = self.rt.request_auto(**get_order_detail(order_id, product_package_id))
        return {value: key for key, value in rep.items() if "" in key}

    async def get_materiel_list(self, product_id):
        """
        获取商品类型及所带物料集合(为订单系统升级准备，目前subtype可以不用)
        :param product_id: 
        :return: 
        """
        response, rep = self.rt.request_auto(**get_single_product_type(product_id))
        return rep

    async def get_subject_video(self, materiel_id):
        """
        查询物料中绑定的视频专题
        :param materiel_id: 
        :return: 
        """
        response, rep = self.rt.request_auto(**get_materiel_detail(materiel_id))
        return rep

    async def get_subject_state(self, subject_video_id):
        """
        校验视频专题是否符合要求
        :param subject_video_id: 
        :return: 
        """
        response, rep = self.rt.request_auto(**get_video_topic_detail(subject_video_id))
        return rep

    async def _run(self, order_id):
        """
        主流程，从商品包开始查起
        :param order_id:
        :return:
        """
        product_package_detail_dict = dict()
        package_data = self.get_product_package(order_id)
        if not package_data:
            return product_package_detail_dict
        for package_id, value in package_data.items():
            product = await self.get_single_product(order_id, package_id)
            product_material = dict()
            # 获取当前版本
            material_version = value[''] or value['']
            for pid, name in product.items():
                if not pid:
                    continue
                product_material[f"{name}({pid})({material_version})"] = None
                material_ids = dict()
                product_data = await self.get_materiel_list(pid)
                # 校验商品类型
                if product_data["subtype"] == "":
                    # 处理重复物料id和没有添加物料的情况
                    for _, material_id in enumerate(product_data[""]):
                        # 过滤重复的物料id
                        if material_id in material_ids:
                            continue
                        material_detail = await self.get_subject_video(material_id)

                        # 过滤与商品版本不一致的物料
                        if not material_detail[""] or material_detail[""] != material_version:
                            continue
                        video_topic_detail = dict()
                        # 处理视频专题，规避专题id为空的情况
                        for _, topic_id in enumerate(material_detail[""].split(",")):
                            if not topic_id:
                                continue
                            vd = await self.get_subject_state(topic_id)
                            video_topic_detail[f"({})"] = vd
                        material_detail[""] = video_topic_detail
                        material_ids[f"({})"] = material_detail
                    product_material[f"{}({})({})"] = material_ids
            product_package_detail_dict.update(
                {f"{[]['']}({})": product_material})
        return product_package_detail_dict

    def do_run(self, order_id):
        return asyncio.run(self._run(order_id))

    def callback(self, _request, r):
        """
        线程结果收集
        :param _request: 线程对象
        :param r: 结果
        :return:
        """
        self.result.update(r if r else dict())

    def get_all_topic(self):
        """
        多线程执行,各订单、商品包没有先后依赖关系，故不需要加锁
        :return:
        """
        ids = self.get_orders()
        if not ids:
            logger.error("\n\t该用户没有已付款订单\n")
            import sys
            sys.exit()
        pool = threadpool.ThreadPool(min(len(ids), 5))
        reqs = threadpool.makeRequests(self.do_run,
                                       ids, callback=self.callback)
        [pool.putRequest(req) for req in reqs]
        pool.wait()

        # 过滤不符合要求的商品包信息
        [self.result.pop(key) for key, value in deepcopy(self.result).items() if not value]

    def main(self):
        try:
            self.get_all_topic()
        except Exception as e:
            logger.error(f"\n\t查询用户专题发生异常: {e}\n")
            return {"success": False, "msg": "查询用户专题发生异常"}
        rj = json_util.dumps(self.result, ensure_ascii=False, indent=1)
        # 写入文件
        folder = f"{base_url}/business/subjectvideo/report"
        if not os.path.exists(folder):
            os.mkdir(folder)
        new_file = f"{folder}/get_sub_video.log"
        with open(new_file, "w+", encoding="utf-8") as f:
            f.write(f"\n\n**************{self.mobile or self.user_id}***************\n"
                    f"时间：{datetime.now()}\n")
            f.flush()
            f.write(rj)
            f.flush()
        return {"success": True, "msg": "详细信息请查看get_sub_video.log"}


if __name__ == '__main__':
    video = GetSubjectVideo()
    video.mobile = 19950000054
    video.main()
